﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>Setting Management</title>
		<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
	</head>

	<body>

		<div class="document-contents">

			<h3 id="DocIntroduction">Introduction</h3>
			<p>Every application need to store some settings and use these settings in 
somewhere in the application. ASP.NET Boilerplate provides a strong 
infrastructure to store/retrieve <strong>application</strong>, <strong>tenant
				</strong>and <strong>user</strong> level settings usable both in <strong>server
				</strong>and <strong>client </strong>sides.</p>
			<p>A setting is a <strong>name-value string</strong> pair that is generally 
stored in a database (or another source). We can store non-string values by 
converting to string.</p>

			<div class="bs-callout bs-callout-warning">
				<h4>About ISettingStore</h4>
				<p>
					<strong>ISettingStore</strong> 
interface must be implemented in order to use setting system. While you can 
implement it in your own way, it's fully implemented in <strong>module-zero</strong> 
project. If it's not implemented, settings are read from application's <strong>
configuration file</strong> (web.config or app.config) but can not change any 
setting. Also, scoping will not work.</p>
			</div>

			<h3 id="DocDefiningSettings">Defining settings</h3>
			<p>A setting must be defined before usage. ASP.NET Boilerplate is designed to be 
				<a href="/Pages/Documents/Module-System">modular</a>. So, different modules can have different settings. A module should 
create a class derived from <strong>SettingProvider </strong>in order to define it's settings. 
An example setting provider is shown below:</p>
			<pre lang="cs">public class MySettingProvider : SettingProvider
{
    public override IEnumerable&lt;SettingDefinition&gt; GetSettingDefinitions(SettingDefinitionProviderContext context)
    {
        return new[]
                {
                    new SettingDefinition(
                        &quot;SmtpServerAddress&quot;,
                        &quot;127.0.0.1&quot;
                        ),

                    new SettingDefinition(
                        &quot;PassiveUsersCanNotLogin&quot;,
                        &quot;true&quot;,
                        scopes: SettingScopes.Application | SettingScopes.Tenant
                        ),

                    new SettingDefinition(
                        &quot;SiteColorPreference&quot;,
                        &quot;red&quot;,
                        scopes: SettingScopes.User,
                        isVisibleToClients: true
                        )

                };
    }
}</pre>
			<p>
				<strong>GetSettingDefinitions</strong> method should return <strong>
SettingDefinition</strong> objects. SettingDefinition class has some 
parameters in it's constructor:</p>
			<ul>
				<li>
					<strong>Name </strong>(required): A setting must have a 
	system-wide <strong>unique </strong>name. It's good idea to define a const 
	string for a setting name instead of a magic string.</li>
				<li>
					<strong>Default value</strong>: A setting may have a default value. This 
	value can be null or empty string.</li>
				<li>
					<strong>Scopes</strong>: A setting should define it's scope (see below).</li>
				<li>
					<strong>Display name</strong>: A localizable string that can be used to 
	show setting's name later in UI.</li>
				<li>
					<strong>Description</strong>: A localizable string that can be used to 
	show setting's description later in UI.</li>
				<li>
					<strong>Group</strong>: Can be used to group settings. This is just for 
	UI, not used in setting management.</li>
				<li>
					<strong>IsVisibleToClients</strong>: Set true to make a setting usable 
	on the client side.</li>
				<li>
					<strong>isInherited</strong>: Used to set if this setting is 
					inherited by tenant and users (See setting scope section).</li>
				<li>
					<strong>customData</strong>: Can be used to set a custom 
					data for this setting definition.</li>
			</ul>
			<p>After creating a setting provider, we should register it in PreIntialize 
method of our module:</p>
			<pre lang="cs">Configuration.Settings.Providers.Add&lt;MySettingProvider&gt;();</pre>
			<p>Setting providers are registered to
				<a href="/Pages/Documents/Dependency-Injection">dependency injection</a> 
automatically. So, a setting provider can inject any dependency (like a 
repository) to build setting definitions using some other sources.</p>
			<h4 id="DocSettingScopes">Setting scope</h4>
			<p>&nbsp;There are three <strong>setting scopes</strong> (or levels) 
defined in <strong>SettingScopes</strong> enum:</p>
			<ul>
				<li>
					<strong>Application</strong>: An application scoped setting is used for 
	user/tenant independed settings. For example, we can define a setting named 
	"SmtpServerAddress" to get server's IP address when sending emails. If this 
	setting has a single value (not changes based on users), then we can define 
	it as Application scoped.</li>
				<li>
					<strong>Tenant</strong>: If the application is multi-tenant, we can 
	define tenant-specific settings.</li>
				<li>
					<strong>User</strong>: We can use a user scoped setting to store/get 
	value of the setting specific to each user.</li>
			</ul>
			<p>SettingScopes enum has <strong>Flags </strong>attribute, so we can define a 
setting with <strong>more than one scopes</strong>.</p>
			<p>Setting scope is <strong>hierarchic</strong> by default (unless 
			you set <strong>isInherited</strong> to false). For example, if we define a 
setting's scope as "Application | Tenant | User" and try to get <strong>current value 
				</strong>of the the 
setting;</p>
			<ul>
				<li>We get the user-specific value if it's defined (overrided) for the user.</li>
				<li>If not, we get the tenant-specific value if it's defined (overrided) for the tenant.</li>
				<li>If not, we get the application value if it's defined.</li>
				<li>If not, we get the <strong>default value</strong>.</li>
			</ul>
			<p>Default value can be <strong>null </strong>or <strong>empty </strong>string. 
It's adviced to provide default values for settings where it's possible.</p>
			<h4>Overriding Setting Definitions</h4>
			<p>context.Manager can be used to get a setting definition to change 
			it's values. In this way, you can manipulate setting definitions of
			<a href="Module-System.html">depended modules</a>.</p>

			<h3 id="DocGettingValues">Getting setting values</h3>
			<p>After defining a setting, we can get it's current value both in server and 
client.</p>
			<h4 id="DocGettingValuesServer">Server side</h4>
			<p>
				<strong>ISettingManager </strong>is used to perform setting 
operations. We can inject and use it anywhere in the application. 
ISettingManager defines many methods to get a setting's value.</p>
			<p>Most used method is <strong>GetSettingValue </strong>(or GetSettingValueAsync 
for async call). It returns <strong>current value </strong>of the setting based 
on default value, application, tenant and user settings (as described in Setting 
scope section before). Examples:</p>
			<pre lang="cs">//Getting a boolean value (async call)
var value1 = await SettingManager.GetSettingValueAsync&lt;bool&gt;(&quot;PassiveUsersCanNotLogin&quot;);

//Getting a string value (sync call)
var value2 = SettingManager.GetSettingValue(&quot;SmtpServerAddress&quot;);
			</pre>
			<p>GetSettingValue has generic and async versions as shown above. There are also methods to get a specific tenant or user's setting value or 
list of all setting values.</p>
			<p>Since ISettingManager is widely used, some special <strong>base classes</strong> (like 
ApplicationService, DomainService and AbpController) has a property named
				<strong>SettingManager</strong>. If we derived from these classes, no need to 
explicitly inject it.</p>
			<h4 id="DocGettingValuesClient">Client side</h4>
			<p>If you set <strong>IsVisibleToClients</strong> as true while defining a 
setting, then you can get it's current value in the client side using 
javascript. <strong>abp.setting</strong> namespace defines needed functions and 
objects. Example:</p>
			<pre lang="js">var currentColor = abp.setting.get("SiteColorPreference");</pre>
			<p>There is also <strong>getInt</strong> and <strong>getBoolean</strong> methods. You can get all values using 
				<strong>abp.setting.values</strong> object. Note that; If you change a setting in server side, clienct can not know this change unless 
page is refreshed, settings are somehow reloaded or it's manually updated by 
code.</p>
			<h3 id="DocChangeSettings">Changing settings</h3>
			<p>ISettingManager defines <strong>ChangeSettingForApplicationAsync</strong>, 
				<strong>ChangeSettingForTenantAsync</strong> and 
				<strong>ChangeSettingForUserAsync </strong>methods (and sync versions) to change settings for 
the application, for a 
tenant and for a user respectively.</p>
			<h3 id="DocCaching">About caching</h3>

			<p>Setting Manager caches settings on the server side. So, we should not directly change 
a setting value using repository or database update query.</p>
		</div>
	</body>

</html>
